home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / tcl / tclmotif.1 / tclmotif / tm.1.2 / src / tmResources.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-03  |  27.8 KB  |  1,118 lines

  1.  
  2. /*
  3.  * TmResources.c --
  4.  *    This module contains the functions to implement resource
  5.  *    handling such as getValues, setValues, and resources
  6.  *
  7.  * Copyright 1993 Jan Newmarch, University of Canberra.
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The author
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #include "tm.h"
  18. #include "tmFuncs.h"
  19. #include <Xm/Xm.h>
  20. #include <Xm/List.h>
  21. #include <Xm/Text.h>
  22.  
  23. /* this is a hack because some converters need info about what
  24.    types they are converting, and Xt does not give such info.
  25.    So we need to place this in globals before calling converters.
  26.    This is to replace the earlier, worse, Tm_MaybeSetTableSize
  27.  */
  28. char *Tm_Resource = NULL;
  29.  
  30.  
  31. /*
  32.  *--------------------------------------------------------------
  33.  *
  34.  * CopyToArgs --
  35.  *
  36.  *    copy to arg of correct size
  37.  *    borrowed from _XtCopyToArgs from Xt lib
  38.  *
  39.  * Results:
  40.  *
  41.  *    new value (of whatever type) stored in dst
  42.  *
  43.  * Side effects:
  44.  *
  45.  *--------------------------------------------------------------
  46.  */
  47. static void 
  48. CopyToArg(src, dst, size)
  49.     char* src;
  50.     XtArgVal *dst;
  51.     register unsigned int size;
  52. {
  53.     if (! (*dst)) {
  54.         if      (size == sizeof(long))     *dst = (XtArgVal)*(long*)src;
  55.         else if (size == sizeof(short))    *dst = (XtArgVal)*(short*)src;
  56.         else if (size == sizeof(char))     *dst = (XtArgVal)*(char*)src;
  57.         else if (size == sizeof(XtPointer)) *dst = (XtArgVal)*(XtPointer*)src;
  58.         else if (size == sizeof(char*))    *dst = (XtArgVal)*(char**)src;
  59.         else if (size == sizeof(XtArgVal)) *dst = *(XtArgVal*)src;
  60.         else bcopy((char*)src, (char*)dst, (int)size);
  61.     }
  62.  
  63. /*
  64.  *--------------------------------------------------------------
  65.  *
  66.  * These functions are all to handle resources that got created
  67.  * and need to be reclaimed
  68.  *
  69.  *--------------------------------------------------------------
  70.  */
  71.  
  72. static Tm_FreeResourceType *Tm_FreeResources = NULL;
  73. static int Tm_FreeResourcesCount;
  74. static int Tm_MaxFreeResourcesCount;
  75.  
  76. typedef struct Tm_FreeResourceStackElmt {
  77.     Tm_FreeResourceType *freeResources;
  78.     int            freeResourcesCount;
  79.     int         maxFreeResourcesCount;
  80. } Tm_FreeResourceStackElmt;
  81.  
  82. static int Tm_FreeResourceStackDepth = 0;
  83. static Tm_FreeResourceStackElmt *Tm_FreeResourceStack = NULL;
  84.  
  85. /*
  86.  *--------------------------------------------------------------
  87.  *
  88.  * Tm_InitFreeResourceList
  89.  *
  90.  *    initialise the list of resources for which space must
  91.  *    be reclaimed after XtSet/GetValues
  92.  *
  93.  *    to allow this to be reentrant, place old entries on stack
  94.  *
  95.  *--------------------------------------------------------------
  96.  */
  97. void Tm_InitFreeResourceList(size)
  98.     int size;
  99. {
  100.  
  101.     /* store any old values if there were any */
  102.     if (Tm_FreeResourceStackDepth > 0) {
  103.     Tm_FreeResourceStack = (Tm_FreeResourceStackElmt *)
  104.         XtRealloc((char *)Tm_FreeResourceStack,
  105.             Tm_FreeResourceStackDepth * 
  106.             sizeof(Tm_FreeResourceStackElmt));
  107.     Tm_FreeResourceStack[Tm_FreeResourceStackDepth - 1].freeResources = 
  108.                 Tm_FreeResources;
  109.     Tm_FreeResourceStack[Tm_FreeResourceStackDepth - 1].freeResourcesCount =
  110.                 Tm_FreeResourcesCount;
  111.     Tm_FreeResourceStack[Tm_FreeResourceStackDepth - 1].maxFreeResourcesCount =
  112.                 Tm_MaxFreeResourcesCount;
  113.  
  114.     }
  115.     Tm_FreeResourceStackDepth++;
  116.  
  117.     if (size <= 0)
  118.     size = 1;
  119.     Tm_FreeResources = (Tm_FreeResourceType *)
  120.             XtMalloc(size * sizeof(Tm_FreeResourceType));
  121.     Tm_FreeResourcesCount = 0;
  122.     Tm_MaxFreeResourcesCount = size;
  123. }
  124.  
  125.  
  126. /*
  127.  *--------------------------------------------------------------
  128.  *
  129.  *  Tm_AddToFreeResourceList
  130.  *
  131.  *    add some data and its corresponding free proc to the list
  132.  *
  133.  *--------------------------------------------------------------
  134.  */
  135. void  Tm_AddToFreeResourceList(data, free)
  136.     char *data;
  137.     Tm_FreeProc free;
  138. {
  139.     /* we only setup the list for adding during a Tm_Set/GetValues
  140.        sequence. We init at the start and free at the end. This
  141.        func gets called by various resource converters. However,
  142.        Motif (or someone else) may be calling our converter outside
  143.        of the Tm_Get/SetValues. We have to assume that they are doing
  144.        their own garbage collect, so need to make sure that we don't
  145.        add for their calls
  146.      */
  147.     if (Tm_FreeResources == NULL)
  148.     return;
  149.  
  150.     /* things like XmStringTables may add many elmts. Grow if needed */
  151.     if (Tm_FreeResourcesCount >= Tm_MaxFreeResourcesCount) {
  152.     Tm_MaxFreeResourcesCount *= 2;
  153.     Tm_FreeResources = (Tm_FreeResourceType *) 
  154.                 XtRealloc((char *)Tm_FreeResources,
  155.                     Tm_MaxFreeResourcesCount * 
  156.                     sizeof(Tm_FreeResourceType));
  157.     }
  158.     Tm_FreeResources[Tm_FreeResourcesCount].data = data;
  159.     Tm_FreeResources[Tm_FreeResourcesCount++].free = free;
  160. }
  161.  
  162.  
  163. /*
  164.  *--------------------------------------------------------------
  165.  * Tm_FreeResourceList
  166.  *
  167.  *    call the free proc on each data elmt of the list
  168.  *
  169.  *--------------------------------------------------------------
  170.  */
  171. void Tm_FreeResourceList()
  172. {
  173.     int n;
  174.     char *data;
  175.     Tm_FreeProc free;
  176.  
  177.     for (n = 0; n < Tm_FreeResourcesCount; n++) {
  178.     free =  Tm_FreeResources[n].free;
  179.     data = Tm_FreeResources[n].data;
  180.     (free) (data);
  181.     }
  182.     XtFree((char *) Tm_FreeResources);
  183.     Tm_FreeResources = NULL;
  184.  
  185.     Tm_FreeResourceStackDepth--;
  186.     if (Tm_FreeResourceStackDepth < 1)
  187.     return;
  188.  
  189.     /* nested calls to Tm_InitFreeResourceList are unwinding - 
  190.        restore values from the stack
  191.      */
  192.     Tm_FreeResources =
  193.         Tm_FreeResourceStack[Tm_FreeResourceStackDepth - 1].freeResources;
  194.     Tm_FreeResourcesCount =
  195.         Tm_FreeResourceStack[Tm_FreeResourceStackDepth - 1].freeResourcesCount;
  196.     Tm_MaxFreeResourcesCount =
  197.         Tm_FreeResourceStack[Tm_FreeResourceStackDepth - 1].maxFreeResourcesCount;
  198. }
  199.  
  200. /*
  201.  *--------------------------------------------------------------
  202.  *
  203.  * Tm_ConvertValue --
  204.  *
  205.  *    convert a value from one format to another
  206.  *
  207.  * Results:
  208.  *
  209.  *    new value (of whatever type) stored in "new_value"
  210.  *
  211.  * Side effects:
  212.  *
  213.  *--------------------------------------------------------------
  214.  */
  215.  
  216. Boolean
  217. Tm_ConvertValue(w, fromType, fromValue, fromSize,
  218.            toType, toValue, toSize)
  219.     Widget w;
  220.     char *fromType;
  221.     char *fromValue;
  222.     unsigned int fromSize;
  223.     char *toType;
  224.     XtArgVal *toValue;
  225.     unsigned int toSize;
  226. {
  227.     XrmValue from, to;
  228.  
  229.     if (strcmp(fromType, toType) == 0) {
  230.     *toValue = (XtArgVal) fromValue;
  231.     return TRUE;
  232.     }
  233.  
  234.     from.size = fromSize;
  235.     from.addr = fromValue;
  236.     to.size = toSize;
  237.     to.addr = XtMalloc(toSize);
  238. /*
  239.     to.addr = NULL;
  240. */
  241.  
  242.     if (!XtConvertAndStore(w, fromType, &from, toType, &to))  {
  243.     fprintf(stderr, "failed conversion %s to %s\n",
  244.                 fromType, toType);
  245.     return FALSE;
  246.     }
  247.     *toValue = 0;
  248.     CopyToArg(to.addr, toValue, to.size);
  249.     XtFree(to.addr);
  250.  
  251.     return TRUE;
  252. }
  253.  
  254. /*
  255.  *--------------------------------------------------------------
  256.  *
  257.  * Tm_ConvertValueFromString --
  258.  *
  259.  *    convert a value from its Tcl string format to the one
  260.  *    the widget wants.
  261.  *
  262.  * Results:
  263.  *
  264.  *    new value (of whatever type) stored in "new_value"
  265.  *
  266.  * Side effects:
  267.  *
  268.  *--------------------------------------------------------------
  269.  */
  270.  
  271. Boolean
  272. Tm_ConvertValueFromString(w, resources, num_resources,
  273.         resource, orig_value, new_value)
  274.     Widget w;
  275.     XtResourceList resources;
  276.     int num_resources;
  277.     char *resource;
  278.     char *orig_value;
  279.     XtArgVal *new_value;
  280. {
  281.     int n;
  282.     XrmValue from, converted;
  283.     XtArgVal tmpval;
  284.     Boolean result;
  285.  
  286. #   ifdef DEBUG
  287.     fprintf(stderr, "converting from string \"%s\" of type %s\n", orig_value, resource);
  288. #   endif
  289.  
  290.     for (n = 0; n < num_resources; n++) {
  291.     if (strcmp(resource, resources->resource_name) == 0) {
  292.         break;
  293.     }
  294.     resources++;
  295.     }
  296.     if (n == num_resources) {
  297.     return FALSE;
  298.     }
  299.  
  300.     /* we have a match - convert and install the resource */
  301.     Tm_Resource = resource;
  302.     result = Tm_ConvertValue(w, XtRString, orig_value,
  303.                 strlen(orig_value)+1,
  304.                 resources->resource_type,
  305.                 new_value,
  306.                 resources->resource_size);
  307.     return result;
  308. }
  309.  
  310. /*
  311.  *--------------------------------------------------------------
  312.  *
  313.  * Tm_ConvertValueFromStringQuark --
  314.  *
  315.  *    convert a value from its Tcl string format to the one
  316.  *    the widget wants. In this form the resources have been
  317.  *    quark'ed so we don't have string compares but int ones
  318.  *
  319.  * Results:
  320.  *
  321.  *    new value (of whatever type) stored in "new_value"
  322.  *
  323.  * Side effects:
  324.  *
  325.  *--------------------------------------------------------------
  326.  */
  327.  
  328. Boolean
  329. Tm_ConvertValueFromStringQuark(w, resources, num_resources,
  330.         resource, orig_value, new_value)
  331.     Widget w;
  332.     XtResourceList resources;
  333.     int num_resources;
  334.     char *resource;
  335.     char *orig_value;
  336.     XtArgVal *new_value;
  337. {
  338.     int n;
  339.     XrmValue from, converted;
  340.     XtArgVal tmpval;
  341.     int resourceQ;
  342.  
  343.     resourceQ = XrmStringToQuark(resource);
  344. #   ifdef DEBUG
  345.     fprintf(stderr, "converting from string \"%s\" of type %s\n",
  346.             orig_value, resource);
  347. #   endif
  348.     for (n = 0; n < num_resources; n++) {
  349.     if (resourceQ == (int) resources->resource_name) {
  350.         break;
  351.     }
  352.     resources++;
  353.     }
  354.     if (n == num_resources) {
  355.     return FALSE;
  356.     }
  357.  
  358.     /* we have a match - convert and install the resource */
  359.     /* special case - same type */
  360.     if (strcmp(XrmQuarkToString((int) resources->resource_type), XtRString) == 0) {
  361.     *new_value =  (XtArgVal) orig_value;
  362.     return TRUE;
  363.     }
  364.     from.size = strlen(orig_value) + 1;
  365.     from.addr = orig_value;
  366.     converted.size = resources->resource_size;
  367.     converted.addr = NULL;
  368.  
  369.     if (!XtConvertAndStore(w, XtRString, &from,
  370.         XrmQuarkToString((int) resources->resource_type), &converted)) {
  371.     return FALSE;
  372.     }
  373.     *new_value = 0;
  374.     CopyToArg(converted.addr, new_value, converted.size);
  375. /* for now
  376.     XtFree(converted.addr);
  377. */
  378. /*
  379.     bzero(new_value, sizeof(XtArgVal));
  380.     bcopy(converted.addr, new_value, converted.size);
  381.     *new_value = *(XtArgVal *) (converted.addr);
  382. */
  383.     
  384.     return TRUE;
  385. }
  386.         
  387.  
  388. /*
  389.  *--------------------------------------------------------------
  390.  *
  391.  * Tm_MaybeSetStringTableSize --
  392.  *
  393.  *    Hack for Motif XmStringTables.
  394.  *    Motif *sometimes* NULL terminates its XmStringTables
  395.  *    most times doesnt.
  396.  *    XmStringGet...() sometimes returns False on running off
  397.  *    the end of a table, sometimes crashes
  398.  *    _XmStringIsXmString() sometimes returns False on running off
  399.  *    the end of a table, sometimes crashes
  400.  *    i.e. there is no internal way of finding the size of one
  401.  *    of these things. So we have to check if we have one and
  402.  *    then look up the resource that tells us the size :-(
  403.  *
  404.  * Results:
  405.  *
  406.  * Side effects:
  407.  *
  408.  *    Sets global vbl Tm_XmStringTableSize
  409.  *--------------------------------------------------------------
  410.  */
  411.  
  412. static void
  413. Tm_MaybeSetStringTableSize(w, resource)
  414.     Widget w;
  415.     String resource;
  416. {
  417.     extern int Tm_XmStringTableSize;
  418.     WidgetClass class;
  419.     Arg arg;
  420.     char *size_resource;
  421.  
  422. #if 0
  423.     class = XtClass(w);
  424.     if (class == xmListWidgetClass) {
  425.     if (strcmp (resource, XmNitems) == 0) {
  426.         size_resource = XmNitemCount;
  427.     } else
  428.     if (strcmp (resource, XmNselectedItems) == 0) {
  429.         size_resource = XmNselectedItemCount;
  430.     } else
  431.     return;
  432.     } else
  433.     return;
  434.  
  435.     /* Sigh, we have a StringTable, find its size */
  436.     XtSetArg(arg, size_resource, &Tm_XmStringTableSize);
  437.     XtGetValues(w, &arg, 1);
  438. #endif
  439. }
  440.  
  441. /*
  442.  *--------------------------------------------------------------
  443.  *
  444.  * Tm_CovertResourceToString --
  445.  *    convert a single resource to a string
  446.  *
  447.  * Results:
  448.  *
  449.  * Side effects:
  450.  *
  451.  *--------------------------------------------------------------
  452.  */
  453.  
  454. Boolean
  455. Tm_ConvertResourceToString(w, resource, resource_size, resource_type, value)
  456.     Widget w;
  457.     char *resource;
  458.     Cardinal resource_size;
  459.     String resource_type;
  460.     char **value;
  461. {
  462.     XrmValue from, converted;
  463.     Arg args[1];
  464.  
  465.     Tm_MaybeSetStringTableSize(w, resource);
  466.  
  467.     from.size = resource_size;
  468.     from.addr = (XtPointer) XtMalloc(from.size);
  469.     XtSetArg(args[0], resource, from.addr);
  470.     XtGetValues(w, args, 1);
  471.     
  472.     /* special case - same type */
  473.     if (strcmp(resource_type, XtRString) == 0) {
  474.     *value =  XtNewString(*(char **) from.addr);
  475.     /* check if it is Text's value */
  476.     if (XtIsSubclass(w, xmTextWidgetClass) &&
  477.         strcmp(resource, XmNvalue) == 0)  {
  478.         XtFree(*(char **) from.addr);
  479.     }
  480.     XtFree(from.addr);
  481.  
  482.     /* allow this to be gc later */
  483.     Tm_AddToFreeResourceList(*value, (Tm_FreeProc) XtFree);
  484.  
  485.     return TRUE;
  486.     }
  487.  
  488.     converted.addr = NULL;
  489.     if (!XtConvertAndStore(w, resource_type, &from,
  490.             XtRString, &converted)) {
  491.     XtFree(from.addr);
  492.     return FALSE;
  493.     }
  494.     bzero(value, sizeof(XtArgVal));
  495.     bcopy(converted.addr, value, converted.size);
  496.     
  497.     XtFree(from.addr);
  498.     return TRUE;
  499. }
  500.  
  501. /*
  502.  *--------------------------------------------------------------
  503.  *
  504.  * Tm_ConvertValueToString --
  505.  *
  506.  *    converts from the internal widget form to a string for Tcl
  507.  *
  508.  * Results:
  509.  *
  510.  * Side effects:
  511.  *
  512.  *--------------------------------------------------------------
  513.  */
  514.  
  515. Boolean
  516. Tm_ConvertValueToString(w, resources, num_resources,
  517.         resource, new_value)
  518.     Widget w;
  519.     XtResourceList resources;
  520.     int num_resources;
  521.     char *resource;
  522.     char **new_value;
  523. {
  524.     int n;
  525.  
  526.     for (n = 0; n < num_resources; n++) {
  527.     if (strcmp(resource, resources->resource_name) == 0) {
  528.         break;
  529.     }
  530.     resources++;
  531.     }
  532.     if (n == num_resources) {
  533.     return FALSE;
  534.     }
  535.  
  536.     Tm_Resource = resource;
  537.     return Tm_ConvertResourceToString(w, resource,
  538.         resources->resource_size, resources->resource_type, new_value);
  539.  
  540. }
  541.         
  542. /*
  543.  *--------------------------------------------------------------
  544.  *
  545.  * Tm_ConvertSubValueFromString --
  546.  *
  547.  *    convert a value from its Tcl string format to the one
  548.  *    the widget wants.
  549.  *
  550.  * Results:
  551.  *
  552.  *    new value (of whatever type) stored in "new_value"
  553.  *
  554.  * Side effects:
  555.  *
  556.  *--------------------------------------------------------------
  557.  */
  558.  
  559. static Boolean
  560. Tm_ConvertSubValueFromString(w, sec_resources, num_sec_resources,
  561.         resource, orig_value, new_value)
  562.     Widget w;
  563.     XmSecondaryResourceData *sec_resources;
  564.     int num_sec_resources;
  565.     char *resource;
  566.     char *orig_value;
  567.     XtArgVal *new_value;
  568. {
  569.     int n, length;
  570.  
  571.     for (n = 0; n < num_sec_resources; n++) {
  572.            if (Tm_ConvertValueFromString(w, sec_resources[n]->resources, 
  573.             sec_resources[n]->num_resources, resource,
  574.                orig_value, new_value)) {
  575.         return True;
  576.     }
  577.     }
  578.     return False;
  579. }
  580.         
  581. /*
  582.  *--------------------------------------------------------------
  583.  *
  584.  * Tm_ConvertSubValueToString --
  585.  *
  586.  *    converts from the internal widget form to a string for Tcl
  587.  *
  588.  * Results:
  589.  *
  590.  * Side effects:
  591.  *
  592.  *--------------------------------------------------------------
  593.  */
  594.  
  595. static Boolean
  596. Tm_ConvertSubValueToString(w, sec_resources, num_sec_resources,
  597.         resource, new_value)
  598.     Widget w;
  599.     XmSecondaryResourceData *sec_resources;
  600.     int num_sec_resources;
  601.     char *resource;
  602.     char **new_value;
  603. {
  604.     int n, length;
  605.  
  606.     for (n = 0; n < num_sec_resources; n++) {
  607.            if (Tm_ConvertValueToString(w, sec_resources[n]->resources, 
  608.             sec_resources[n]->num_resources, resource,
  609.                new_value)) {
  610.         return True;
  611.     }
  612.     }
  613.     return False;
  614. }
  615.  
  616. /*
  617.  *--------------------------------------------------------------
  618.  *
  619.  * Tm_FreeSecondaryResources --
  620.  *
  621.  *    Motif gives us a copy of these, so we have to tidy up
  622.  *
  623.  * Results:
  624.  *
  625.  * Side effects:
  626.  *
  627.  *--------------------------------------------------------------
  628.  */
  629.  
  630. void
  631. Tm_FreeSecondaryResources(sec_resources, num_sec_resources)
  632.     XmSecondaryResourceData *sec_resources;
  633.     int num_sec_resources;
  634. {
  635.     int n;
  636.  
  637.     for (n = 0; n < num_sec_resources; n++) {
  638.     XtFree((char *) sec_resources[n]->resources);
  639.     XtFree((char *) sec_resources[n]);
  640.     }
  641.  
  642.     if (num_sec_resources > 0) {
  643.         XtFree((char *) sec_resources);
  644.     }
  645. }
  646.  
  647. /*
  648.  *--------------------------------------------------------------
  649.  *
  650.  * Tm_SetValues --
  651.  *
  652.  *    set resource values on a widget
  653.  *
  654.  * Results:
  655.  *     a tcl result
  656.  *
  657.  * Side effects:
  658.  *
  659.  *--------------------------------------------------------------
  660.  */
  661.  
  662. int
  663. Tm_SetValues(pathName, interp, w, parent, class, argv, argc, args, num_args)
  664.     char *pathName;
  665.     Tcl_Interp *interp;
  666.     Widget w;
  667.     Widget parent;
  668.     WidgetClass class;
  669.     char **argv;
  670.     int argc;
  671.     Arg args[];
  672.     int *num_args;
  673. {
  674.     XtResourceList resources, constraint_resources;
  675. #ifndef MOTIF11
  676.     XmSecondaryResourceData *sec_resources;
  677.     int num_sec_resources;
  678. #endif
  679.     Cardinal num_resources;
  680.     Cardinal num_constraint_resources;
  681.     int num_values = 0;
  682.     XrmValue from, converted;
  683.     XtArgVal new_value;
  684.     char *resource;
  685.     char *value;
  686.     Tm_ClientData *client_data;
  687.  
  688.     *num_args = 0;
  689.  
  690.     if (argc > TM_MAXARGS*2) {
  691.     return TCL_ERROR;
  692.     }
  693.  
  694.     XtGetResourceList(class, &resources, &num_resources);
  695. #ifndef MOTIF11
  696.     num_sec_resources = XmGetSecondaryResourceData(class, &sec_resources);
  697. #endif
  698.     if (parent != NULL && XtIsConstraint(parent)) {
  699.     XtGetConstraintResourceList(XtClass(parent), 
  700.         &constraint_resources, &num_constraint_resources);
  701.     } else {
  702.     num_constraint_resources = 0;
  703.     }
  704.  
  705.     while (argc >= 2) {
  706.     if (argv[0][0] != '-') {
  707.         sprintf(interp->result, "illegal setValues option \"%50s\"", argv[0]);
  708.         return TCL_ERROR;
  709.     }
  710.     resource = argv[0]+1;
  711.         value = argv[1];
  712.  
  713.         /* we cant allow callbacks to be converted - too messy */
  714.         if (strstr(resource, "Callback") != NULL) {
  715.         sprintf(interp->result, "setValues doesn't support callbacks.\
  716. Use \"%s\" method\n", resource);
  717.           return TCL_ERROR;
  718.         }
  719.  
  720.         if (Tm_ConvertValueFromString(w, resources, num_resources,
  721.         resource, value, &new_value)) {
  722.             XtSetArg(args[num_values], resource, new_value);
  723.         num_values++;
  724.     } else
  725.         if (num_constraint_resources > 0 &&
  726.         Tm_ConvertValueFromString(w, constraint_resources, 
  727.                 num_constraint_resources, resource,
  728.                 value, &new_value)) {
  729.             XtSetArg(args[num_values], resource, new_value);
  730.         num_values++;
  731.     } else 
  732. #ifndef MOTIF11
  733.         if (num_sec_resources > 0 &&
  734.         Tm_ConvertSubValueFromString(w, sec_resources, 
  735.                 num_sec_resources, resource,
  736.                 value, &new_value)) {
  737.             XtSetArg(args[num_values], resource, new_value);
  738.         num_values++;
  739.     } else
  740. #endif
  741.     {
  742.         sprintf(interp->result, "Conversion from String to \"%50s\" failed\n",
  743.                                 resource);
  744.         return TCL_ERROR;
  745.     }
  746.     argc -= 2;
  747.     argv += 2;
  748.     }
  749.  
  750. #ifndef MOTIF11
  751.     if (num_sec_resources > 0)
  752.     Tm_FreeSecondaryResources(sec_resources, num_sec_resources);
  753. #endif /* MOTIF11 */
  754.     if (num_resources > 0) 
  755.     XtFree((char *) resources);
  756.     if (num_constraint_resources > 0) 
  757.     XtFree((char *) constraint_resources);
  758.  
  759.     *num_args = num_values;
  760.     return TCL_OK;
  761. }
  762.  
  763. /*
  764.  *--------------------------------------------------------------
  765.  *
  766.  * Tm_GetValues --
  767.  *
  768.  *    get the resource values out of a widget
  769.  *
  770.  * Results:
  771.  *    a tcl result
  772.  *
  773.  * Side effects:
  774.  *
  775.  *--------------------------------------------------------------
  776.  */
  777.  
  778. int
  779. Tm_GetValues(pathName, interp, w, class, argv, argc)
  780.     char *pathName;
  781.     Tcl_Interp *interp;
  782.     Widget w;
  783.     WidgetClass class;
  784.     char **argv;
  785.     int argc;
  786. {
  787.     XtResourceList resources, constraint_resources;
  788. #ifndef MOTIF11
  789.     XmSecondaryResourceData *sec_resources;
  790.     int num_sec_resources;
  791. #endif
  792.     Cardinal num_resources;
  793.     Cardinal num_constraint_resources;
  794.     int num_values = 0;
  795.     XrmValue from, converted;
  796.     char *new_value;
  797. #   define MAXARGS 100
  798.     char *resource;
  799.     Tm_ClientData *client_data;
  800.     Widget parent;
  801.  
  802.     if (argc > MAXARGS*2) {
  803.     return TCL_ERROR;
  804.     }
  805.  
  806.     parent = XtParent(w);    /* this is NULL for w == "." */
  807.     XtGetResourceList(class, &resources, &num_resources);
  808.  
  809. #ifndef MOTIF11
  810.     num_sec_resources = XmGetSecondaryResourceData(class, &sec_resources);
  811. #endif
  812.   
  813.     if (parent != NULL && XtIsConstraint(parent)) {
  814.     XtGetConstraintResourceList(XtClass(parent), 
  815.         &constraint_resources, &num_constraint_resources);
  816.     } else {
  817.     num_constraint_resources = 0;
  818.     }
  819.  
  820.     while (argc >= 2) {
  821.     if (argv[0][0] != '-') {
  822.         sprintf(interp->result, "illegal setValues option \"%50s\"", argv[0]);
  823.         return TCL_ERROR;
  824.     }
  825.     resource = argv[0]+1;
  826.  
  827.         if (Tm_ConvertValueToString(w, resources, num_resources,
  828.         resource, &new_value)) {
  829.         /* store new_value in variable in argv[1] now */
  830. #        ifdef DEBUG
  831.         fprintf(stderr, "Got value: %s\n", (char *) new_value);
  832. #        endif
  833.         if (Tcl_SetVar(interp, argv[1], (char *) new_value,
  834.             TCL_LEAVE_ERR_MSG) == NULL)
  835.         fprintf(stderr, "%s\n", interp->result);
  836.     } else
  837.         if (num_constraint_resources > 0 &&
  838.         Tm_ConvertValueToString(w, constraint_resources, 
  839.                 num_constraint_resources, resource,
  840.                 &new_value)) {
  841.         /* store in a variable now */
  842.         if (Tcl_SetVar(interp, argv[1], (char *) new_value,
  843.             TCL_LEAVE_ERR_MSG) == NULL)
  844.         fprintf(stderr, "%s\n", interp->result);
  845.     } else 
  846. #ifndef MOTIF11
  847.         if (num_sec_resources > 0 &&
  848.         Tm_ConvertSubValueToString(w, sec_resources, 
  849.                 num_sec_resources, resource,
  850.                 &new_value)) {
  851.         /* store in a variable now */
  852.         if (Tcl_SetVar(interp, argv[1], (char *) new_value,
  853.             TCL_LEAVE_ERR_MSG) == NULL)
  854.         fprintf(stderr, "%s\n", interp->result);
  855.     } else
  856. #endif
  857.     {
  858.         sprintf(interp->result, "Conversion from %s to String failed\n",
  859.                     resource);
  860.         return TCL_ERROR;
  861.     }
  862.     argc -= 2;
  863.     argv += 2;
  864.     }
  865. #ifndef MOTIF11
  866.     if (num_sec_resources > 0)
  867.     Tm_FreeSecondaryResources(sec_resources, num_sec_resources);
  868. #endif
  869.     if (num_resources > 0) 
  870.     XtFree((char *) resources);
  871.     if (num_constraint_resources > 0) 
  872.     XtFree((char *) constraint_resources);
  873.     return TCL_OK;
  874. }
  875.  
  876. /*
  877.  *--------------------------------------------------------------
  878.  *
  879.  * Tm_ResourceInfo --
  880.  *
  881.  *    get the resource info out of a widget
  882.  *
  883.  * Results:
  884.  *    a tcl result
  885.  *
  886.  * Side effects:
  887.  *
  888.  *--------------------------------------------------------------
  889.  */
  890.  
  891. void
  892. Tm_GetResourceInfo(resourceInfo, w, resource)
  893.     Tcl_DString *resourceInfo;
  894.     Widget w;
  895.     XtResource *resource;
  896. {
  897.     char *resource_value;
  898.  
  899.     Tcl_DStringAppend(resourceInfo, "-", 1);
  900.     Tcl_DStringAppend(resourceInfo, resource->resource_name, -1);
  901.     Tcl_DStringAppendElement(resourceInfo, resource->resource_name);
  902.     Tcl_DStringAppendElement(resourceInfo, resource->resource_class);
  903.     Tcl_DStringAppendElement(resourceInfo, resource->resource_type);
  904.  
  905.     /* hack to let resource converter know what this is */
  906.     Tm_Resource = resource->resource_name;
  907.  
  908.     if (Tm_ConvertResourceToString(w, resource->resource_name,
  909.         resource->resource_size, resource->resource_type,
  910.         &resource_value)) {;
  911.         Tcl_DStringAppendElement(resourceInfo, resource_value);
  912.     } else {
  913.         Tcl_DStringAppendElement(resourceInfo, "");
  914.     }
  915. }
  916. /*
  917.  *--------------------------------------------------------------
  918.  *
  919.  * Tm_NoErrorMsg --
  920.  *
  921.  * Results:
  922.  *     none
  923.  *
  924.  * Side effects:
  925.  *    does nothing
  926.  *
  927.  *--------------------------------------------------------------
  928.  */
  929.  
  930. void
  931. Tm_NoErrorMsg(name, type, Class, defalt, params, num_params)
  932.     String name;
  933.     String type;
  934.     String Class;
  935.     String defalt;
  936.     String *params;
  937.     Cardinal *num_params;
  938. {
  939.     /* void */
  940. }
  941.  
  942.  
  943. /*
  944.  *--------------------------------------------------------------
  945.  *
  946.  * Tm_ResourceList --
  947.  *
  948.  *    get the resource list out of a widget
  949.  *
  950.  * Results:
  951.  *    a tcl result
  952.  *
  953.  * Side effects:
  954.  *
  955.  *--------------------------------------------------------------
  956.  */
  957.  
  958. int
  959. Tm_ResourceList(interp, w, class)
  960.     Tcl_Interp *interp;
  961.     Widget w;
  962.     WidgetClass class;
  963. {
  964.     XtResourceList resources, constraint_resources;
  965. #ifndef MOTIF11
  966.     XmSecondaryResourceData *sec_resources;
  967.     int num_sec_resources;
  968. #endif
  969.     Cardinal num_resources;
  970.     Cardinal num_constraint_resources;
  971.     int num_values = 0;
  972.     char *new_value;
  973.     char *resource;
  974.     Tm_ClientData *client_data;
  975.     Widget parent;
  976.     int m, n;
  977.     Tcl_DString resourceList, resourceInfo;
  978.     XtErrorHandler oldWarningHandler;
  979.  
  980.     parent = XtParent(w);    /* this is NULL for w == "." */
  981.     XtGetResourceList(class, &resources, &num_resources);
  982.  
  983. #ifndef MOTIF11
  984.     num_sec_resources = XmGetSecondaryResourceData(class, &sec_resources);
  985. #endif
  986.   
  987.     if (parent != NULL && XtIsConstraint(parent)) {
  988.     XtGetConstraintResourceList(XtClass(parent), 
  989.         &constraint_resources, &num_constraint_resources);
  990.     } else {
  991.     num_constraint_resources = 0;
  992.     }
  993.  
  994.     /* turn off error messages about converters that we don't support */
  995.     oldWarningHandler = XtAppSetWarningHandler(XtWidgetToApplicationContext(w), 
  996.                     Tm_NoErrorMsg);
  997.  
  998.     /* set up for garbage collect of resource values */
  999.     Tm_InitFreeResourceList(128);
  1000.  
  1001.     Tcl_DStringInit(&resourceList);
  1002.  
  1003.     Tcl_DStringInit(&resourceInfo);
  1004.     for (n = 0; n < num_resources; n++) {
  1005.     Tm_GetResourceInfo(&resourceInfo, w, resources+n);
  1006.     /* hack to get string out of D-string */
  1007. /*
  1008.     Tcl_DStringResult(interp, &resourceInfo);
  1009.     Tcl_DStringAppendElement(&resourceList, interp->result);
  1010. */
  1011.  
  1012.     /* no, do it the proper way (accessing internals of DString :-(  ) */
  1013.     Tcl_DStringAppendElement(&resourceList, resourceInfo.string);
  1014.     Tcl_DStringFree(&resourceInfo);
  1015.     Tcl_DStringInit(&resourceInfo);
  1016.     }
  1017.  
  1018. #   ifndef MOTIF11
  1019.     Tcl_DStringInit(&resourceInfo);
  1020.     for (n = 0; n < num_sec_resources; n++) {
  1021.     for (m = 0; m < sec_resources[n]->num_resources; m++) {
  1022.         Tm_GetResourceInfo(&resourceInfo, w, &(sec_resources[n]->resources[m]));
  1023.         /* hack to get string out of D-string */
  1024.         Tcl_DStringResult(interp, &resourceInfo);
  1025.         Tcl_DStringAppendElement(&resourceList, interp->result);
  1026.     }
  1027.     }
  1028. #   endif
  1029.  
  1030.     Tcl_DStringInit(&resourceInfo);
  1031.     for (n = 0; n < num_constraint_resources; n++) {
  1032.     Tm_GetResourceInfo(&resourceInfo, w, constraint_resources+n);
  1033.     /* hack to get string out of D-string */
  1034.     Tcl_DStringResult(interp, &resourceInfo);
  1035.     Tcl_DStringAppendElement(&resourceList, interp->result);
  1036.     }
  1037.  
  1038.     /* turn error reporting back on */
  1039.     XtAppSetWarningHandler(XtWidgetToApplicationContext(w), oldWarningHandler);
  1040.  
  1041.     Tcl_DStringResult(interp, &resourceList);
  1042.  
  1043. #ifndef MOTIF11
  1044.     if (num_sec_resources > 0)
  1045.     Tm_FreeSecondaryResources(sec_resources, num_sec_resources);
  1046. #endif
  1047.     if (num_resources > 0) 
  1048.     XtFree((char *) resources);
  1049.     if (num_constraint_resources > 0) 
  1050.     XtFree((char *) constraint_resources);
  1051.     Tm_FreeResourceList();
  1052.  
  1053.     return TCL_OK;
  1054. }
  1055.  
  1056. /*
  1057.  *--------------------------------------------------------------
  1058.  *
  1059.  * Tm_GetAppResources -- get the resources specific to the
  1060.  *    application level
  1061.  *
  1062.  * Results:
  1063.  *     standard tcl result
  1064.  *
  1065.  * Side effects:
  1066.  *    sets tcl vbls with the application resources
  1067.  *
  1068.  *--------------------------------------------------------------
  1069.  */
  1070.  
  1071. int
  1072. Tm_GetAppResources(interp, w, resource_str)
  1073.     Tcl_Interp *interp;
  1074.     Widget w;
  1075.     String resource_str;
  1076. {
  1077.     char **resource_list;
  1078.     int num_resources;
  1079.     char **res_elmts;
  1080.     int num_elmts;
  1081.     XtResourceList resources;
  1082.     String *vbls;
  1083.     String *values;
  1084.     int n;
  1085.  
  1086.     Tcl_SplitList(interp, resource_str, &num_resources, &resource_list);
  1087.     resources = (XtResource *) XtMalloc(num_resources * sizeof(XtResource));
  1088.     vbls = (String *) XtMalloc(num_resources * sizeof(String));
  1089.     values = (String *) XtMalloc(num_resources * sizeof(String));
  1090.  
  1091.     for (n = 0; n < num_resources; n++) {
  1092.     Tcl_SplitList(interp, resource_list[n], &num_elmts, &res_elmts);
  1093.     if (num_elmts != 4) {
  1094.         sprintf(interp->result, "wrong getAppResources \"%50s\"",
  1095.             resource_list[n]);
  1096.        return TCL_ERROR;
  1097.     }
  1098.  
  1099.     resources[n].resource_name = res_elmts[0];
  1100.     resources[n].resource_class = res_elmts[1];
  1101.     resources[n].resource_type = XtRString;
  1102.     resources[n].resource_offset = n * sizeof(String);
  1103.     resources[n].default_type = XtRString;
  1104.     resources[n].default_addr = res_elmts[2];
  1105.  
  1106.     vbls[n] = res_elmts[3];
  1107.     }
  1108.  
  1109.     XtGetApplicationResources(w, values, resources, num_resources, NULL, 0);
  1110.  
  1111.     for (n = 0; n < num_resources; n++) {
  1112.     Tcl_SetVar(interp, vbls[n], values[n], 0);
  1113.     }
  1114.  
  1115.     return TCL_OK;
  1116. }
  1117.